
import { fromEvent,  Observable, Subject } from 'rxjs';
import { map, takeUntil, concatAll} from 'rxjs/operators';

interface IZCustomEvent {}
/**
 * @description 对mousedown、mousemove、mouseup分装
 * @author zengwe
 * @date 2019/09/10
 */
export class Events {
    protected mousedown: Observable<MouseEvent>;
    protected mouseup: Observable<MouseEvent>;
    protected mousemove: Observable<MouseEvent>;
    public dragStartEvt: Subject<CustomEvent<IZCustomEvent>> = new Subject();
    public dragMoveEvt: Subject<CustomEvent<IZCustomEvent>> = new Subject();
    public dragEndEvt: Subject<CustomEvent<IZCustomEvent>> = new Subject();
    constructor(private ele: HTMLElement) {
        this.bindEvent();
    }
    public bindEvent() {
        this.mousedown = fromEvent<MouseEvent>(this.ele, 'mousedown');
        this.mouseup = fromEvent<MouseEvent>(this.ele, 'mouseup');
        this.mousemove = fromEvent<MouseEvent>(this.ele, 'mousemove');
        this.eventMove();
    }
    protected eventMove() {
        let startEvt: MouseEvent;
        let isStart: boolean = false;
        let mov: any;
        let test = this.mousedown.pipe(
            map(downEv => {
                startEvt =  downEv;
                this.dragStartEvt.next(this.createCustomEvent(downEv,'dragStartEvt'));
                let mov = this.mousemove.pipe(takeUntil(this.mouseup.pipe(
                    map(msUp => {
                        if(msUp.timeStamp - startEvt.timeStamp > 300) {
                            isStart = false;  
                            startEvt = <any>undefined;
                            this.dragEndEvt.next(this.createCustomEvent(msUp, 'dragEndEvt'));
                        }
                        return msUp;
                    })
                ))).pipe(map(mvEvt => {
                    if(mvEvt.timeStamp - startEvt.timeStamp > 300 || (Math.abs(mvEvt.clientX - startEvt.clientX) > 20 || Math.abs(mvEvt.clientY - startEvt.clientY) > 20)) {
                        if(isStart == false) {
                            this.dragStartEvt.next(this.createCustomEvent(startEvt,'dragStartEvt'));
                            isStart = true;
                        }else{
                           // this.dragMoveEvt.next(this.createCustomEvent(mvEvt, 'dragMoveEvt')); 
                           this.dragMoveEvt.next(this.createCustomEvent({start: startEvt, end: mvEvt}, 'dragMoveEvt'));
                        } 
                    }
                    return mvEvt;
                }));
                return mov;
            }),
            concatAll()
        );
        test.subscribe(res => {
            // console.log('end')
        }, (err) => {

        }, () => {
            console.log('complete')
        });
    }
    /**
     * 
     * @param originEvent MouseEvent
     * @param name string
     * @param canBubbleArg default true
     * @param cancelableArg default false
     */
    private createCustomEvent(originEvent: any, name: string, canBubbleArg: boolean = true, cancelableArg: boolean = false): CustomEvent<IZCustomEvent> {
        let Event = document.createEvent('CustomEvent');
        Event.initCustomEvent(name, canBubbleArg,cancelableArg, originEvent);
        return Event;
    }
}
